package cn.eeepay.framework.dao;

import cn.eeepay.framework.db.pagination.Page;
import cn.eeepay.framework.model.AccountAddress;
import cn.eeepay.framework.model.AccountAddressLog;
import cn.hutool.core.util.StrUtil;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.jdbc.SQL;

import java.util.List;
import java.util.Map;

/**
 * 账单地
 *
 * @author hzl
 * @date 2020/11/12
 */
public interface AccountAddressDao {


    @Insert("insert into account_address(address,address_type,total_amount,reserved_amount,local_used,other_used,release_time,min_amount,max_amount," +
            "start_time,end_time,open_status,create_time,join_group_polling) values(#{ac.address},#{ac.addressType},#{ac.totalAmount},#{ac.reservedAmount},#{ac.localUsed}," +
            "#{ac.otherUsed},#{ac.releaseTime},#{ac.minAmount},#{ac.maxAmount},#{ac.startTime},#{ac.endTime},#{ac.openStatus},#{ac.createTime},#{ac.joinGroupPolling})")
    int insert(@Param("ac") AccountAddress ac);

    @Delete("delete from account_address")
    int delete();

    @Update("UPDATE account_address set total_amount = #{ad.totalAmount},address = #{ad.address},address_type = #{ad.addressType},reserved_amount = #{ad.reservedAmount}," +
            "release_time = #{ad.releaseTime},min_amount = #{ad.minAmount},max_amount = #{ad.maxAmount}," +
            "start_time = #{ad.startTime},end_time = #{ad.endTime},open_status = #{ad.openStatus},join_group_polling = #{ad.joinGroupPolling} where id = #{ad.id}")
    int update(@Param("ad") AccountAddress accountAddress);

    @Select("select * from account_address")
    List<AccountAddress> select(@Param("page") Page<AccountAddress> page);

//    @SelectProvider(type = SqlProvider.class, method = "accountAddressPage")
//    @ResultType(AccountAddress.class)
//    List<AccountAddress> accountAddressPage(@Param("accountAddress") AccountAddress accountAddress, @Param("page") Page<AccountAddress> page);

    @Select("select * from account_address where address = #{address}")
    @ResultType(AccountAddress.class)
    AccountAddress findAccountAddressByAddress(String address);

    @Update("update account_address set join_group_polling = #{status} where id = #{id}")
    void updateJoinGroupPollingStatus(@Param("id") Integer id, @Param("status") Integer status);

    @Update("update account_address set open_status = #{status} where id = #{id}")
    void updateOpenStatus(@Param("id") Integer id, @Param("status") Integer status);

    @Select("select SUM(o.trans_amount) trans_amount,o.jump_id,c.remark from account_addr_order o left join jump_route_config c on c.id = o.jump_id " +
            "where o.mer_province = #{merProvince} and o.account_date = #{date} group by o.jump_id")
    @ResultType(List.class)
    List<Map<String, Object>> collectAccoundAddrOrderByMerProvinceAndDate(@Param("merProvince") String merProvince, @Param("date") String date);

    @Select("select SUM(o.trans_amount) trans_amount,o.jump_id,c.remark from account_addr_order o left join jump_route_config c on c.id = o.jump_id " +
            "where o.account_address = #{accountAddress} and o.account_date = #{date} group by o.jump_id")
    @ResultType(List.class)
    List<Map<String, Object>> collectAccoundAddrOrderByAccountAddressAndDate(@Param("accountAddress") String accountAddress, @Param("date") String date);

//    @Select("select sum(total_amount) total_amount from account_address where address = #{address} and start_time >= #{startTime} and end_time <= #{endTime}")
//    BigDecimal collectAccountAddrTotalAmount(@Param("address") String address, @Param("startTime") String startTime, @Param("endTime") String endTime);

//    @Select("select * from account_address where address = #{address} and start_time >= #{startTime} and end_time <= #{endTime}")
//    @ResultType(AccountAddress.class)
//    AccountAddress findAccountAddress(@Param("address") String address, @Param("startTime") String startTime, @Param("endTime") String endTime);

    @Select("select sum(a.trans_amount) used_quota,a.account_address address,a.account_date " +
            "from account_addr_order a where a.account_date = #{accountDate} group by a.account_address")
    @ResultType(AccountAddressLog.class)
    List<AccountAddressLog> collectAccountAddrOrder(String accountDate);

    @Select("select * from account_address where id = #{id}")
    @ResultType(AccountAddress.class)
    AccountAddress findById(Integer id);

    @SelectProvider(type = SqlProvider.class, method = "findToDayAccountAddressByDateAndAccountAddressAndType")
    @ResultType(AccountAddress.class)
    List<AccountAddress> findToDayAccountAddressByDateAndAccountAddressAndType(@Param("address") String address, @Param("type") Integer type, @Param("page") Page<AccountAddress> page);

    @SelectProvider(type = SqlProvider.class, method = "findHistoryAccountAddressByDateAndAccountAddressAndType")
    @ResultType(AccountAddress.class)
    List<AccountAddress> findHistoryAccountAddressByDateAndAccountAddressAndType(@Param("dateStart") String dateStart, @Param("dateEnd") String dateEnd, @Param("address") String address, @Param("type") Integer type, @Param("page") Page<AccountAddress> page);


    public class SqlProvider {

        public String findToDayAccountAddressByDateAndAccountAddressAndType(final Map<String, Object> param) {
            final String address = (String) param.get("address");
            final Integer type = (Integer) param.get("type");
            return new SQL() {
                {
                    SELECT("address,address_type,release_time,reserved_amount,local_used,other_used");
                    FROM("account_address");
                    if (StrUtil.isNotBlank(address)) {
                        WHERE("address like concat(#{address},'%')");
                    }
                    if (type != null && type != -1) {
                        WHERE("address_type = #{type}");
                    }
                }
            }.toString();
        }

        public String findHistoryAccountAddressByDateAndAccountAddressAndType(final Map<String, Object> param) {
            final String address = (String) param.get("address");
            final Integer type = (Integer) param.get("type");
            return new SQL() {
                {
                    SELECT("address,address_type,release_time,reserved_amount,used_quota local_used,other_used,account_date");
                    FROM("account_address_log");
                    if (StrUtil.isNotBlank(address)) {
                        WHERE("address like concat(#{address},'%')");
                    }
                    if (type != null && type != -1) {
                        WHERE("address_type = #{type}");
                    }
                    WHERE("account_date BETWEEN #{dateStart} and #{dateEnd}");
                    ORDER_BY("account_date desc");
                }
            }.toString();
        }
    }
}
